| TOP | スクリプト解説 | リンク | ご意見板 |


98Like!別館
敵が弾を撃ってみよう(自機との当たり判定もしちゃうよ)♪
98Like!本館はコチラ




さあ、いよいよ敵が弾を撃ちます。これで、シューティングのオーソドックスな形は整いますね。って言っても、とてもゲームとは言えませんけど・・・。

まず毎度お馴染み3行目にスクリプトを見やすく・分かりやすくする為に、よく使う『
TAMAMAX』と言うマクロを定義します。(あくまでも分かりやすくする為ですので、『TAMAMAX=36』の様に変数扱いとしても同様の結果になります)

次に
『*SYOKIKA』の所に『myl=1』と敵弾の各種設定情報の初期化を追加します。

次に
『*MAIN』メインルーチンですが、ココにまたも1つサブルーチン『gosub *TAMAMOVE』を追加します。このサブルーチンで敵弾の移動と自機との当たり判定を行います。また、自機がやられてしまった時に、自機の表示移動サブルーチンに飛ばないように『if myl>0 : gosub *JIKI』この様にして時期が存在するときだけサブルーチンに飛ぶように変更します。

次に
『*TEKIMOVE』内に、敵弾を発生させるタイミングと発生時の各種初期値を設定します。まず、『rnd tam,200 : if tam=0 : {』乱数を発生させてその値が0だった場合に『{』以下を実行します。要するに乱数の値が0だったときに弾が発生します。乱数の範囲を大きくすれば弾が出るタイミングが遅くなり、範囲を小さくすればどんどん弾が出てきます。色々と数字を変えてお試し下さい。
次に敵弾は複数(今回は合計36発)存在するので『
repeat〜loop』を使用して、まだ表示されていない敵弾を探す為に敵弾数だけループさせます。
次の『
tf.cnt<1 : continue』ですが、これも毎度お馴染みですが敵弾が既に存在していれば以後の発生処理を飛ばすという意味です。
次に、弾の存在フラッグを立てて、弾発生の初期位置を設定します。
更に乱数を利用して敵弾の初期移動量を決定します。また同じように乱数を利用して、敵弾の種類(ここでは真直ぐ下に落ちる弾と斜め下に飛ぶ弾)を決めています。その後、弾を出した敵の位置と自機の位置との差を求めて、自機に近い方向(左OR右)へ移動するように移動量を決定します。
最後に『
break』ですが、これを入れないと1機の敵から最大36発の弾が一度に発射されてしまい、とんでもない事になってしまいます。

さあ、
『*TAMAMOVE』ここからが今回のメインです・・・・って言っても前回の「敵の移動と当たり判定」と基本的には同じです。
まず、弾が存在しなければその後の処理を飛ばします。存在していれば、弾の移動処理をして、前回同様
二重ループを利用して自機弾と敵弾の当たり判定を行います。(自機弾で敵弾を打ち落とす事が出来る場合です。)
次に自機との当たり判定ですが、自機は画面上に1機しか存在しないので
二重ループの必要は無く、そのまま絶対値を求めて処理を行います。

最後に敵弾を新しい座標に描画をしてこのルーチンも終わりです。



今回は、基本部分が前回と同じなので説明を大幅に端折りました。分かりにくい場所があれば、掲示板やメールにてご質問下さい m(_ _)m
とにかく、
二重ループの注意と当たり判定の原理さえ憶えてしまえば、後はほとんど同じなので格段に作業がラクチンになります♪
下記のスクリプトの一部または全部において転用は自由とさせていただきますので、色々と数字を換えてお試し下さい♪
下記スクリプトをHSPのスクリプトエディターにコピペでお使いいただけます。



 

   
	#define SHOTMAX 2			;自機弾最大数
	#define ENEMYMAX 12			;敵機最大数
	#define TAMAMAX 36			;敵弾最大数

	buffer 2,,,1 
	picload "cruiser.bmp"
	screen 0,640,480,1,dispx-640/2,dispy-480/2:cls 4 : title "space cruiser" 
	font "MS 明朝",20 
	gmode 2


*SYOKIKA 
	mx=300 : my=400			;自機の初期位置 
	lv=1				;初期レベル
	myl=1				;自機生存の有無

	dim sf,SHOTMAX			;自弾の有無 
	dim sx,SHOTMAX			;自弾のX座標 
	dim sy,SHOTMAX			;自弾のY座標 

	dim ef,ENEMYMAX			;敵の硬さ
	dim ex,ENEMYMAX			;敵のX座標
	dim ey,ENEMYMAX			;敵のY座標
	dim et,ENEMYMAX			;敵発生からのカウンター
	dim esx,ENEMYMAX			;敵のX軸移動量
	dim esy,ENEMYMAX			;敵のY軸移動量

	dim tf,TAMAMAX			;敵弾の有無
	dim tx,TAMAMAX			;敵弾のX座標
	dim ty,TAMAMAX			;敵弾のY座標
	dim tk,TAMAMAX			;敵弾の種類(垂直OR斜頚)
	dim td,TAMAMAX			;敵弾の弾道(方向)
	dim ts,TAMAMAX			;敵弾の移動速度


*MAIN					;メインループ 
	palcolor 0 : boxf 0,0,640,480 
	if myl>0 : gosub *JIKI 
	gosub *TAMA
	if enemy=0 : gosub *TEKI
	gosub *TEKIMOVE
	gosub *TAMAMOVE
	redraw 1 : redraw 2 : await 30 
	goto *MAIN 

 
*JIKI					;自機の移動・ショットキーチェック 
	stick bt,5 : k- : if k<1 : if bt&16 : ff=1 : k=3 
	mxv=(bt&4!0):mxv-=(bt&1!0) 
	mx+=mxv*8 
	if mx<0 : mx=0 
	if mx>580 : mx=580 
	pos mx,my : gcopy 2,0,32,64,64 
	return 

 
*TAMA					;自機弾の移動・表示
	repeat SHOTMAX 
	if ff>0 : if sf.cnt=0 : ff- : sf.cnt=1 : sx.cnt=mx+16 : sy.cnt=my-20 
	if sf.cnt=0 : continue 
	sy.cnt-=12 : if sy.cnt<-32 : sf.cnt=0 
	pos sx.cnt,sy.cnt : gcopy 2,96,0,32,32 
	loop 
	return

*TEKI					;敵の出現
	repeat ENEMYMAX
	if cnt<12	{
	if cnt<10	{
	if cnt<8	{
	if cnt<6	{
	if cnt<4	{
	if cnt<2	{	ef.cnt=1 : ex.cnt=cnt*100+100 : ey.cnt=80
			pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32
		}else{	ef.cnt=1 : ex.cnt=cnt-2*100+100 : ey.cnt=130
			pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32	}
		}else{	ef.cnt=1 : ex.cnt=cnt-4*100+100 : ey.cnt=180
			pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32	}
		}else{	ef.cnt=1 : ex.cnt=cnt-5*100+300 : ey.cnt=80
			pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32	}
		}else{	ef.cnt=1 : ex.cnt=cnt-7*100+300 : ey.cnt=130
			pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32	}
		}else{	ef.cnt=1 : ex.cnt=cnt-9*100+300 : ey.cnt=180
			pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32	}
		} 
		esx.cnt=5 : esy.cnt=5 : et.cnt=0
		enemy=1
	loop
return

*TEKIMOVE					;敵の移動処理・当たり判定
	repeat ENEMYMAX
	if ef.cnt<1 : continue
	et.cnt++
	if cnt<6 {
		ex.cnt-=esx.cnt : if et.cnt>20 : et.cnt=-20 : esx.cnt=-esx.cnt
		ey.cnt+=esy.cnt : if (ey.cnt>200)|(ey.cnt<50) : esy.cnt=-esy.cnt
	}else{
		ex.cnt+=esx.cnt : if et.cnt>20 : et.cnt=-20 : esx.cnt=-esx.cnt
		ey.cnt+=esy.cnt : if (ey.cnt>200)|(ey.cnt<50) : esy.cnt=-esy.cnt
	}
	ent=cnt
		repeat SHOTMAX
		if sf.cnt=0 : continue
		dx=(ex.ent+16)-(sx.cnt+16) : if dx<0 : dx=-dx
		dy=(ey.ent+16)-(sy.cnt+16) : if dy<0 : dy=-dy
		if dx<10 : if dy<10 {
		ef.ent- : sf.cnt- : pos ex.ent,ey.ent : palcolor 255 : mes "●"
		}
		loop
		rnd tam,200 : if tam=0 {
		repeat TAMAMAX
		if tf.cnt>0 : continue
		tf.cnt+ : tx.cnt=ex.ent : ty.cnt=ey.ent
		rnd ts.cnt,5 : ts.cnt+=5
		rnd tk.cnt,3 : if tk.cnt=0 : tk.cnt=1
		dx=ex.ent-mx : if dx<0 : td.cnt=-3 : else : td.cnt=3
		break
		loop
		}
	pos ex.cnt,ey.cnt : gcopy 2,lv*32,0,32,32
	loop
return

*TAMAMOVE					;敵弾の移動&当たり判定
	repeat TAMAMAX
	if tf.cnt<1 : continue
	if tk.cnt=1 : ty.cnt+=ts.cnt : else : ty.cnt+=ts.cnt : tx.cnt-=td.cnt
	if ty.cnt>480 : tf.cnt-
	ent=cnt
		repeat SHOTMAX
			if sf.cnt=0 : continue
			dx=(tx.ent+16)-(sx.cnt+16) : if dx<0 : dx=-dx
			dy=(ty.ent+16)-(sy.cnt+16) : if dy<0 : dy=-dy
			if dx<5 : if dy<10 {
			tf.ent- : sf.cnt- : pos sx.cnt,sy.cnt : palcolor 255 : mes "●"
			}
		loop
		if myl<1 : continue
		dx=(tx.cnt+16)-(mx+32) : if dx<0 : dx=-dx
		dy=(ty.cnt+16)-(my+32) : if dy<0 : dy=-dy
		if dx<20 : if dy<30 {
		tf.cnt- : myl- : pos mx,my : palcolor 255 : mes "○◎○"
		}
	pos tx.cnt,ty.cnt : gcopy 2,128,0,32,32
	loop
return
		


↑こんな感じです。敵弾発生と自機との当たり判定追加♪
これで一応はゲームになりましたね(^^);


上手く出来たら、次に行ってみましょう♪

NEXT ->>


管理人 : よっしー

テレワークならECナビ Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!
無料ホームページ 無料のクレジットカード 海外格安航空券 海外旅行保険が無料! 海外ホテル